package com.fg.cloud.manager.service.system.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.fg.cloud.common.construction.Button;
import com.fg.cloud.common.construction.Resource;
import com.fg.cloud.common.construction.Tree;
import com.fg.cloud.common.dictionary.DicUtils;
import com.fg.cloud.manager.entry.BaseEntity;
import com.fg.cloud.manager.entry.system.MenuEntity;
import com.fg.cloud.manager.entry.system.vo.MenuVo;
import com.fg.cloud.manager.mapper.BaseMapper;
import com.fg.cloud.manager.mapper.system.MenuMapper;
import com.fg.cloud.manager.service.BaseServiceImpl;
import com.fg.cloud.manager.service.system.MenuService;

/**
 * @author ：
 * @date ： 2017年6月12日 下午7:31:26
 * @Desc ：菜单具体实现service
 */
@Service
public class MenuServiceImpl extends BaseServiceImpl implements MenuService {

	@Autowired
	private MenuMapper menuMapper;

	@Override
	protected <T extends BaseEntity> BaseMapper getBaseMapper() {
		return menuMapper;
	}

	@Override
	public List<Tree> findAllMenu(Integer classify) {
		Tree tree = null, parentTree = null;
		String ids = "";
		List<Tree> childList = null;
		// 获取所有菜单项
		List<MenuVo> menuList = classify == 0 ? menuMapper.selectAll() : menuMapper.selectByType(classify);
		Map<Long, Tree> treeMap = new HashMap<Long, Tree>();

		for (MenuVo menu : menuList) {
			tree = convert(menu);
			if (tree.getPid() == null || tree.getPid() == 0) {// 处理父菜单与子菜单不同逻辑，子菜单插入父菜单list
				ids += tree.getId() + ",";
				treeMap.put(tree.getId(), tree);
			} else {
				parentTree = treeMap.get(tree.getPid());
				childList = parentTree.getChildren() != null ? parentTree.getChildren() : new ArrayList<Tree>();
				childList.add(tree);
				parentTree.setChildren(childList);
				treeMap.put(parentTree.getId(), parentTree);
			}
		}
		// 迭代Map，根据ids记录顺序封装到list
		childList = new ArrayList<Tree>();
		if (ids.length() > 0)
			for (String id : ids.split("[, ]+")) {
				childList.add(treeMap.get(Long.valueOf(id)));
			}
		return childList;
	}

	@Override
	public List<Resource> findByUserId(Long userId, Integer type) {
		Map<Long, List<Resource>> map = new HashMap<Long, List<Resource>>();
		Map<Long, List<String>> buttonMap = new HashMap<Long, List<String>>();
		List<MenuVo> menuList = menuMapper.selectMenuByUserId(type, userId);
		List<Resource> childList = null;
		List<String> buttonList = null;
		Resource res = null;
		MenuVo menu = null;

		for (int i = 0; i < menuList.size(); i++) {
			menu = menuList.get(i);
			res = convertResource(menu);
			// 判断资源是菜单还是按钮
			if (DicUtils.RESOURCE_BUTTON == res.getType()) {
				if (null == buttonMap.get(menu.getPid()))
					buttonList = new ArrayList<String>();
				else
					buttonList = buttonMap.get(menu.getPid());

				// if(null != buttonMap.get(menu.getId())) res.setMeta(new
				// Button(buttonMap.get(menu.getPid())));

				buttonList.add(menu.getUrl());
				buttonMap.put(menu.getPid(), buttonList);
			} else {
				if (null == map.get(menu.getPid()))
					childList = new ArrayList<Resource>();
				else
					childList = map.get(menu.getPid());
				// 查找当前级资源是否存在下级
				if (null != map.get(menu.getId())) {
					res.setChildren(map.get(menu.getId()));
				}
				if (null != buttonMap.get(menu.getId()))
					res.setMeta(new Button(buttonMap.get(menu.getId())));

				childList.add(res);
				map.put(menu.getPid(), childList);
			}
		}
		return map.get(0L);

		/*
		 * List<Tree> treeList = new ArrayList<Tree>(); Map<Long, List<Tree>>
		 * map = new HashMap<Long, List<Tree>>();
		 * 
		 * List<MenuVo> menuList = menuMapper.selectMenuByUserId(type, userId);
		 * List<Tree> childList = null; Tree tree = null;
		 * 
		 * //Tree结构封装循环查询的用户菜单按钮权限，从内往外依次封装 for (int i = 0; i < menuList.size();
		 * i++) { tree = convert(menuList.get(i));
		 * //当不存在上级集合，则创建一个，存在则直接从map取已有数据的 if(null == map.get(tree.getPid()))
		 * childList = new ArrayList<Tree>(); else childList =
		 * map.get(tree.getPid()); //查找当前级菜单是否存在下级内容，有则封装到当前级 if(null !=
		 * map.get(tree.getId())) tree.setChildren(map.get(tree.getId()));
		 * 
		 * childList.add(tree); map.put(tree.getPid(), childList); } return
		 * treeList
		 */
	}

	@Override
	public List<Tree> findByRoleId(Long roleId, Integer classify) {
		// 返回结果集
		// List<Tree> treeList = new ArrayList<Tree>();
		// 封装树形结构数据
		Map<Long, List<Tree>> treeMap = new HashMap<Long, List<Tree>>();
		List<MenuVo> menuList = menuMapper.selectMenuByRoleId(classify, roleId);
		List<Tree> childList = null;
		Tree tree = null;// parentTree = null;
		// String rootIds = "";//统计根级id

		for (MenuVo menu : menuList) {
			tree = convert(menu);
			if (null == treeMap.get(menu.getPid()))
				childList = new ArrayList<Tree>();
			else
				childList = treeMap.get(menu.getPid());
			// 查找当前级资源是否存在下级
			if (null != treeMap.get(menu.getId())) {
				tree.setChildren(treeMap.get(menu.getId()));
			}

			childList.add(tree);
			treeMap.put(menu.getPid(), childList);
		}
		return treeMap.get(0L);
		// //获取所有菜单
		// List<Tree> menuList = findAllMenu(classify);
		// List<Long> userMenuIds = menuMapper.selectByRoleId(roleId, classify);
		//
		// for(Tree tree : menuList) {
		// //没有父级菜单权限的跳过子菜单
		// if(!userMenuIds.contains(tree.getId())) continue;
		// //选中当前父菜单
		// tree.setChecked(true);
		// for(Tree child : tree.getChildren())
		// if(userMenuIds.contains(child.getId())) child.setChecked(true);
		// }
		// return menuList;
	}

	/**
	 * Menu ==> Resource
	 * 
	 * @param menu
	 *            MenuVo
	 * @return Resource
	 */
	private Resource convertResource(MenuVo menu) {
		Resource res = new Resource();
		res.setId(menu.getId());
		res.setName(menu.getName());
		res.setPath(menu.getUrl());
		res.setComponent(menu.getPermission());
		res.setType(menu.getType());
		res.setIcon(menu.getIcon());
		return res;
	}

	/**
	 * MenuEntity ==> Tree
	 * 
	 * @param menu
	 *            MenuEntity
	 * @return Tree
	 */
	private Tree convert(MenuVo menu) {
		Tree tree = new Tree();
		tree.setId(menu.getId());
		tree.setPid(menu.getParentId());
		tree.setLabel(menu.getName());
		tree.setNumber(menu.getNumber());
		tree.setUrl(menu.getUrl());
		tree.setPermission(menu.getPermission());
		tree.setSeq(menu.getSeq());
		tree.setType(menu.getType());
		tree.setText(menu.getName());
		tree.setIcon(menu.getIcon());
		tree.setRemark(menu.getRemark());
		tree.setVisible(menu.getVisible() == 0 ? false : true);
		tree.setChecked(menu.getChecked() == 0 ? false : true);
		return tree;
	}

	@Override
	public List<Tree> findList(Integer classify) {
		// 返回结果集
		List<Tree> treeList = new ArrayList<Tree>();
		// 封装树形结构数据
		Map<Long, Tree> treeMap = new HashMap<Long, Tree>();
		List<MenuVo> menuList = menuMapper.selectList(classify);
		List<Tree> childList = null;
		Tree tree = null, parentTree = null;
		String rootIds = "";// 统计根级id

		for (MenuVo menu : menuList) {
			tree = convert(menu);
			if (tree.getPid() == 0) {// 处理父菜单与子菜单不同逻辑，子菜单插入父菜单list
				rootIds += tree.getId() + ",";
				treeMap.put(tree.getId(), tree);
			} else {
				if (tree.getType() < 2) {// 处理当不为按钮级别时，依旧加入封装处理
					treeMap.put(tree.getId(), tree);
				}
				parentTree = treeMap.get(tree.getPid());
				childList = parentTree.getChildren() != null ? parentTree.getChildren() : new ArrayList<Tree>();
				childList.add(tree);
				parentTree.setChildren(null);
				parentTree.setChildren(childList);
				treeMap.put(parentTree.getId(), parentTree);
			}
		}

		for (String id : rootIds.split("[, ]+")) {
			treeList.add(treeMap.get(Long.valueOf(id)));
		}
		return treeList;
	}

	@Transactional
	public boolean insertSelective(MenuEntity entity) {
		return menuMapper.insertSelective(entity) > 0 ? true : false;
	}

	@Override
	@Transactional
	public boolean deletes(Long id, String number) {
		Long[] ids = menuMapper.selectByNumber(id, number + "_" + id);
		if (ids.length > 30) {
			Object[] longs=splitAry(ids,30);
			for (Object obj : longs) {
				menuMapper.deleteByMenuId((Long[])obj);
			}
		}else{
			menuMapper.deleteByMenuId(ids);
		}
		return menuMapper.deletes(id, number + "_" + id) > 0 ? true : false;
	}
	
	@Override
	@Transactional
	public boolean sysDeletes(Long id, String number) {
		Long[] ids = menuMapper.selectByNumber(id, number + "_" + id);
		if (ids.length > 30) {
			Object[] longs=splitAry(ids,30);
			for (Object obj : longs) {
				menuMapper.deleteByMenuId((Long[])obj);
			}
		}else{
			menuMapper.deleteByMenuId(ids);
		}
		return menuMapper.sysDeletes(id, number + "_" + id) > 0 ? true : false;
	}

	/**
	  * Description:数组拆分工具
	  * @param ary
	  * @param subSize
	  * @return
	  * @author shaoqiping
	  * @date 2017年8月24日上午11:18:38
	*/
	private static Object[] splitAry(Long[] ary, int subSize) {
		int count = ary.length % subSize == 0 ? ary.length / subSize : ary.length / subSize + 1;
		List<List<Long>> subAryList = new ArrayList<List<Long>>();
		for (int i = 0; i < count; i++) {
			int index = i * subSize;
			List<Long> list = new ArrayList<Long>();
			int j = 0;
			while (j < subSize && index < ary.length) {
				list.add(ary[index++]);
				j++;
			}
			subAryList.add(list);
		}
		Object[] subAry = new Object[subAryList.size()];
		for (int i = 0; i < subAryList.size(); i++) {
			List<Long> subList = subAryList.get(i);
			Long[] subAryItem = new Long[subList.size()];
			for (int j = 0; j < subList.size(); j++) {
				subAryItem[j] = subList.get(j).longValue();
			}
			subAry[i] = subAryItem;
		}
		return subAry;
	}

	@Override
	public Set<String> findMenuUrlByUserId(Long userId) {
		return menuMapper.selectMenuUrlByUserId(userId);
	}

	@Override
	@Transactional
	public boolean move(Long id, Integer seq, Long changeId,
			Integer changeSeq) {
		MenuEntity entity = new MenuEntity();
		entity.setId(id);
		entity.setSeq(changeSeq);
		MenuEntity change = new MenuEntity();
		change.setId(changeId);
		change.setSeq(seq);
		int count = menuMapper.updateByPrimaryKeySelective(change);
		count += menuMapper.updateByPrimaryKeySelective(entity);
		return count == 2;
	}

}
